package com.lntea.netty.reconnect;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;

/**
 * Title: ReconnectClient.java<br>
 * Description:  通过netty实现可信赖的重连机制<br>
 * Copyright: Copyright (c) 2015<br>
 * Company: 北京云杉世界信息技术有限公司<br>
 *
 * @author lichao
 * @date 2019/11/12 11:31
 */
public class ReconnectClient {
    static final String HOST = System.getProperty("host", "127.0.0.1");
    static final int PORT = Integer.parseInt(System.getProperty("port", "8080"));

    // 尝试重连前等待时间
    static final int RECONNECT_DELAY = Integer.parseInt(System.getProperty("reconnectDelay", "5"));
    // 服务器多长时间未响应执行重连
    static final int READ_TIMEOUT = Integer.parseInt(System.getProperty("readTimeout", "10"));

    private static final ReconnectClientHandler handler = new ReconnectClientHandler();
    private static final Bootstrap b = new Bootstrap();

    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup group = new NioEventLoopGroup();

        try {
            b.group(group)
                    .channel(NioSocketChannel.class)
                    .remoteAddress(HOST, PORT)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline()
                                    .addLast(new LoggingHandler(LogLevel.INFO),
                                            new IdleStateHandler(READ_TIMEOUT, 0, 0),
                                            handler);
                        }
                    });
            ChannelFuture f = b.connect().sync();
            f.channel().closeFuture().sync();
        } finally {
            // 异常不能释放事件线程组，否则不能执行重连操作
            // group.shutdownGracefully();
        }
    }

    static void connect() {
        b.connect().addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                if (channelFuture.cause() != null) {
                    handler.startTime = -1;
                    handler.println("Failed to connect: " + channelFuture.cause());
                }
            }
        });
    }
}
